﻿using System;
using System.Collections.Generic;
using System.Text;
using System.ComponentModel;
using Sinacor.Infra.Common.Exceptions;
using Sinacor.Infra.Service.ExceptionHandling;
using Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum;
using Sinacor.Infra.Service.Common;


namespace Sinacor.Servico.Bovespa.Ordens.BusinessLogic
{
    public class PreBoleto : BaseBusinessLogic
    {
        #region Constantes de Erros
        private const int ERRO_PRECOINVALIDO = 103000;
        private const int ERRO_CONTRAPARTEINVALIDA = 103001;
        private const int ERRO_ESTRATEGIAINVALIDA = 103002;
        private const int ERRO_CAMBIOINVALIDO = 103003;
        private const int ERRO_QUANTIDADENEGOCIOINVALIDA = 103004;
        private const int ERRO_TITULONAOENCONTRADO = 103005;
        private const int ERRO_ORDEMDISTRIBUIDA = 103006;
        private const int ERRO_ORDEMINEXISTENTE = 103007;
        private const int ERRO_PREBOLETONAOINFORMADO = 103008;
        private const int ERRO_PREBOLETO_PREBOLETOINVALIDONAEXCLUSAO = 103177;
        private const int ERRO_PREBOLETO_ORDENSDIFERENTESSAOINVALIDAS = 103178;
        #endregion

        /// <summary>
        /// Data: 01/12/2007
        /// Autor: Diogo Milanez
        /// Obs: Criacao do Metodo
        /// 
        /// Data : 28/01/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : Obter fator de cotação do titulo usado no calculo do volume
        /// 
        /// Data : 07/02/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : Alterada assinatura do metodo ConsultarTituloCodigo de 2 para 1 parametro.
        /// </summary>
        /// <param name="ordem"></param>
        /// <returns></returns>
        public List<BusinessEntity.PreBoleto> ConsultarPreBoleto(BusinessEntity.Ordem ordem)
        {
            BusinessEntity.Ordem beOrdem = new ResourceAccess.Ordem().ConsultarOrdem(ordem);

            if (beOrdem == null)
            {
                throw new BusinessException(ERRO_ORDEMINEXISTENTE);
            }
            ordem.IndicadorDesprezaSaldo = beOrdem.IndicadorDesprezaSaldo;//incluido - rvaladao - 20080413

            Titulo.BusinessEntity.Titulo beTituloRequest = new Titulo.BusinessEntity.Titulo(); //incluido - eduardo - 20080207
            beTituloRequest.Codigo = beOrdem.Titulo; //incluido - eduardo - 20080207
            beTituloRequest.DataOrdem = beOrdem.DataOrdem.Value; //incluido - eduardo - 20080207
            Titulo.BusinessEntity.Titulo beTitulo = (new Titulo.ResourceAccess.Titulo()).ConsultarTituloCodigo(beTituloRequest); //alterado - eduardo - 20080207

            if (beTitulo == null)
            {
                throw new BusinessException(ERRO_TITULONAOENCONTRADO);
            }

            List<BusinessEntity.PreBoleto> retorno = (new ResourceAccess.PreBoleto()).ConsultarSintetico(ordem, beTitulo.FatorCotacao.Value);
            
            return retorno;
        }

        /// <summary>
        /// Data: 01/12/2007
        /// Autor: Diogo Milanez
        /// Obs: Criacao do Metodo
        /// 
        /// Data : 28/01/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : Obter fator de cotação do titulo usado no calculo do volume
        /// 
        /// Data : 07/02/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : Alterada assinatura do metodo ConsultarTituloCodigo de 2 para 1 parametro (apenas BusinessEntity.Titulo)
        /// </summary>
        /// <param name="ordem"></param>
        /// <returns></returns>
        public List<BusinessEntity.PreBoleto> ConsultarPreBoletoAnalitico(BusinessEntity.Ordem ordem)
        {
            BusinessEntity.Ordem beOrdem = new ResourceAccess.Ordem().ConsultarOrdem(ordem);

            if (beOrdem == null)
            {
                throw new BusinessException(ERRO_ORDEMINEXISTENTE);
            }
            
            ordem.IndicadorDesprezaSaldo = beOrdem.IndicadorDesprezaSaldo;//incluido - rvaladao - 20080417
            Titulo.BusinessEntity.Titulo beTituloRequest = new Titulo.BusinessEntity.Titulo(); //incluido - eduardo - 20080207
            beTituloRequest.Codigo = beOrdem.Titulo; //incluido - eduardo - 20080207
            beTituloRequest.DataOrdem = beOrdem.DataOrdem.Value; //incluido - eduardo - 20080207
            Titulo.BusinessEntity.Titulo beTitulo = (new Titulo.ResourceAccess.Titulo()).ConsultarTituloCodigo(beTituloRequest); //alterado - eduardo - 20080207

            if (beTitulo == null)
            {
                throw new BusinessException(ERRO_TITULONAOENCONTRADO);
            }

            List<BusinessEntity.PreBoleto> retorno = (new ResourceAccess.PreBoleto()).ConsultarAnalitico(ordem, beTitulo.FatorCotacao.Value);

            return retorno;
        }

        ///Diogo Milanez - 21/11/2007
        ///Operacao removida
        //public void RealizarDescasamentoPreBoleto(BusinessEntity.PreBoleto preBoleto)
        //{
        //	ValidarDadosDescasamento(preBoleto);
        //
        //	ResourceAccess.PreBoleto preBoletoRA = new ResourceAccess.PreBoleto();
        //	preBoletoRA.RealizarDescasamento(preBoleto);
        //	preBoletoRA = null;
        //
        //	return;
        //}

        /// <summary>
        /// Metodo responsavel por incluir uma colecao de pre-boletos
        /// Data: 21/11/2007
        /// Autor: Diogo Milanez
        /// Obs:
        /// * Parametro de entrada passou a ser uma colecao
        /// * Retorno passou a ser void
        /// * Adicionado parametro realizarCasamento
        /// Data: 30/11/2007
        /// Autor: Diogo Milanez
        /// Obs:
        /// Parametro de retorno foi alterado de void para RetornoCasamentoPreBoleto
        /// </summary>
        /// <param name="request">colecao de pre-boletos para inclusao</param>
        /// <param name="realizarCasamento">flag utilizado para indicar que devera ser realizado 
        /// o casamento de pre-boletos apos a inclusao da colecao de pre-boletos informada</param>
        public BusinessEntity.RetornoCasamento IncluirPreBoleto(List<BusinessEntity.PreBoleto> request, bool realizarCasamento)
        {
            if (request == null || request.Count == 0)
                throw new BusinessException(ERRO_PREBOLETONAOINFORMADO);

            return EfetuarInclusaoPreBoleto(request, realizarCasamento);
        }

        private Sinacor.Servico.Bovespa.Ordens.BusinessEntity.RetornoCasamento EfetuarInclusaoPreBoleto(List<BusinessEntity.PreBoleto> request, bool realizarCasamento)
        {
            ResourceAccess.PreBoleto preBoletoRA = new ResourceAccess.PreBoleto();

            BusinessLogic.Ordem ordemBL = new BusinessLogic.Ordem();

            ///checar se a ordem ja foi distribuida, caso tenha sido n permitir a inclusao do
            ///pre-boleto
            if (ordemBL.VerificarOrdemDistribuida(request[0].Ordem, request[0].DataPregao))
            {
                throw new BusinessException(ERRO_ORDEMDISTRIBUIDA);
            }

            ///realizar a validacao dos pre-boletos informados
            ValidarDadosInclusao(request);

            ///apos validar todos os preboletos sendo incluidos
            ///chamar a inclusao de cada preBoleto
            foreach (BusinessEntity.PreBoleto preBoleto in request)
            {
                if (!preBoleto.Cambio.HasValue || preBoleto.Cambio == 0)
                    preBoleto.Cambio = 1;

                BusinessEntity.Ordem beOrdem = ordemBL.ConsultarOrdem(preBoleto.Ordem);

                if (beOrdem == null)
                {
                    throw new BusinessException(ERRO_ORDEMINEXISTENTE);
                }

                preBoleto.Ordem = beOrdem;

                preBoletoRA.Incluir(preBoleto);
            }

            if (realizarCasamento)
            {
                return RealizarCasamentoESP(request[0]);
            }
            else
                return null;
        }


        /// <summary>
        /// Metodo responsavel por excluir uma colecao de pre-boletos
        /// Alteracoes:
        /// Diogo Milanez - 21/11/2007
        /// * Parametro de entrada passou a ser uma colecao de pre-boletos
        /// * Adicionado paramento realizarCasamento
        /// 
        /// Data : 30/01/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : Obter data do pregao a partir do pre boleto na TORDETD
        /// </summary>
        /// <param name="request">colecao de pre-boletos para exclusao</param>
        /// <param name="realizarCasamento">flag utilizado para indicar que devera ser realizado 
        /// o casamento de pre-boletos apos a exclusao da colecao de pre-boletos informada</param>
        public void ExcluirPreBoleto(List<BusinessEntity.PreBoleto> request, bool realizarDescasamento)
        {
            if (request == null || request.Count == 0)
                throw new BusinessException(ERRO_PREBOLETONAOINFORMADO);

            EfetuarExclusaoPreBoleto(request, realizarDescasamento);
        }

        private BusinessEntity.RetornoCasamento EfetuarExclusaoPreBoleto(List<BusinessEntity.PreBoleto> request, bool realizarDescasamento)
        {
            ResourceAccess.PreBoleto preBoletoRA = new ResourceAccess.PreBoleto();

            BusinessLogic.Ordem ordemBL = new BusinessLogic.Ordem();

            //incluido - eduardo - 20080130
            foreach (BusinessEntity.PreBoleto preBoletoItem in request)
            {
                DateTime? dataPregao = preBoletoRA.ConsultarDataPregaoPreBoleto(preBoletoItem);
                if (dataPregao == null)
                {
                    throw new BusinessException(ERRO_PREBOLETO_PREBOLETOINVALIDONAEXCLUSAO);
                }
                preBoletoItem.DataPregao = dataPregao.Value;
            }

            ///checar se a ordem ja foi distribuida, caso tenha sido n permitir a inclusao do
            ///pre-boleto
            if (ordemBL.VerificarOrdemDistribuida(request[0].Ordem, request[0].DataPregao))
            {
                throw new BusinessException(ERRO_ORDEMDISTRIBUIDA);
            }

            BusinessEntity.RetornoCasamento retorno = null;
            //validar e excluir a lista de pre-boletos informada
            foreach (BusinessEntity.PreBoleto preBoletoItem in request)
            {
                ValidarDadosExclusao(preBoletoItem);
                preBoletoRA.Excluir(preBoletoItem);
                if (realizarDescasamento)
                {
                    retorno =RealizarDescasamento(preBoletoItem);
                }
            }
            return retorno;
        }

        /// <summary>
        /// Metodo responsavel por processar duas colecoes de pre-boletos
        /// uma de exclusao e uma de inclusao
        /// </summary>
        /// <param name="requestInclusao">colecao de pre-boletos para inclusao</param>
        /// <param name="requestExclusao">colecao de pre-boletos para exclusao</param>
        /// <param name="requestAlteracao">colecao de pre-boletos para alteracao</param>
        public BusinessEntity.RetornoCasamento ProcessarPreBoleto(List<BusinessEntity.PreBoleto> requestInclusao, List<BusinessEntity.PreBoleto> requestExclusao, List<BusinessEntity.PreBoleto> requestAlteracao)
        {
            if ((requestExclusao == null || requestExclusao.Count == 0) &&
                (requestInclusao == null || requestInclusao.Count == 0) &&
                (requestAlteracao == null || requestAlteracao.Count == 0))
            {
                ValidationException ex = new ValidationException();
                ex.AddError(ERRO_PREBOLETONAOINFORMADO);
                throw ex;
            }

            //verifica se todos os pre-boletos sao da mesma ordem
            ValidarOrdemPreBoletos(requestInclusao, requestExclusao);

            //20080424 10:32 - RValadao
            //Tratamento do retorno do casamento para alteração ou inclusão.
            BusinessEntity.RetornoCasamento retorno = null;

            //caso tenha informado pre-boletos para exclusao
            if (requestExclusao != null && requestExclusao.Count > 0)
            {
                //excluir pre-boletos
                //20080424 17:07 - RValadao
                //Inclusao de retorno de mensagem ao efetuar a exclusão
                retorno = EfetuarExclusaoPreBoleto(requestExclusao, true);
            }


            if (requestAlteracao != null && requestAlteracao.Count > 0)
            {
                retorno = AlterarPreBoleto(requestAlteracao);
            }

            if (requestInclusao != null && requestInclusao.Count > 0)
            {
                //incluir pre-boletos
                EfetuarInclusaoPreBoleto(requestInclusao, false);
                retorno = RealizarCasamentoESP(requestInclusao[0]);
            }


            return retorno;
        }

        /// <summary>
        /// Data : 31/01/2008
        /// Autor: Eduardo Sertorio
        /// Obs. : Criacao do metodo - validar se todos os pre-boletos sao da mesma ordem.
        /// </summary>
        /// <param name="requestInclusao"></param>
        /// <param name="requestExclusao"></param>
        private void ValidarOrdemPreBoletos(List<BusinessEntity.PreBoleto> requestInclusao, List<BusinessEntity.PreBoleto> requestExclusao)
        {
            string chaveant = "";
            string chaveatu = chaveant;
            bool primeiroItem = true;

            if ((requestInclusao != null) && (requestInclusao.Count > 0))
            {
                foreach (BusinessEntity.PreBoleto preBoletoItem in requestInclusao)
                {
                    StringBuilder str = new StringBuilder();
                    str.Append(preBoletoItem.Ordem.DataOrdem.ToString());
                    str.Append(";");
                    str.Append(preBoletoItem.Ordem.NumeroOrdem.ToString());
                    str.Append(";");
                    str.Append(preBoletoItem.Ordem.NumeroOrdemSubSequencia.ToString());
                    str.Append(";");
                    chaveatu = str.ToString();

                    if (!chaveatu.Equals(chaveant) && !primeiroItem)
                    {
                        throw new BusinessException(ERRO_ORDEMINEXISTENTE);
                    }
                    chaveant = chaveatu;
                    primeiroItem = false;
                }
            }

            if ((requestExclusao != null) && (requestExclusao.Count > 0))
            {
                foreach (BusinessEntity.PreBoleto preBoletoItem in requestExclusao)
                {
                    StringBuilder str = new StringBuilder();
                    str.Append(preBoletoItem.Ordem.DataOrdem.ToString());
                    str.Append(";");
                    str.Append(preBoletoItem.Ordem.NumeroOrdem.ToString());
                    str.Append(";");
                    str.Append(preBoletoItem.Ordem.NumeroOrdemSubSequencia.ToString());
                    str.Append(";");
                    chaveatu = str.ToString();

                    if (!chaveatu.Equals(chaveant) && !primeiroItem)
                    {
                        throw new BusinessException(ERRO_PREBOLETO_ORDENSDIFERENTESSAOINVALIDAS);
                    }
                    chaveant = chaveatu;
                }
            }
        }

        /// <summary>
        /// Metodo responsavel por realizar o casamento de pre-boletos
        /// armazenados na base
        /// Historico:
        /// Data: 29/11/2007
        /// Autor: Diogo Milanez
        /// Observacoes:Criacao do metodo 
        /// Data: 29/11/2007
        /// Autor: Diogo Milanez
        /// Obs: Tipo de retorno foi alterado de int32 para RetornoCasamentoPreBoleto
        /// </summary>
        /// <returns>objeto contendo informacoes de retorno do processamento</returns>
        public BusinessEntity.RetornoCasamento RealizarCasamentoESP(BusinessEntity.PreBoleto preBoleto)
        {
            BusinessEntity.RetornoCasamento retorno;
            ResourceAccess.PreBoleto preBoletoRA = new ResourceAccess.PreBoleto();
            //20080410 15:07 - RValadao.7Comm
            //A data pregao de ordem estava null e então passou a receber do datapregao do preboleto
            preBoleto.Ordem.DataPregao = preBoleto.DataPregao;
            retorno = preBoletoRA.RealizarCasamento(preBoleto.Ordem, BusinessEntity.Enum.TipoCasamentoPreBoleto.ESP);
            if (retorno == null) return null;

            RealizarAcoesPosCasamentoDescasamento(preBoleto, retorno, "Casamento de Pré-Boletos");

            return retorno;
        }
        
        /// <summary>
        /// Metodo responsavel por realizar o casamento de pre-boletos
        /// </summary>
        /// <returns>objeto contendo informacoes de retorno do processamento</returns>
        public BusinessEntity.RetornoCasamento RealizarCasamento(BusinessEntity.PreBoleto preBoleto, BusinessEntity.Enum.TipoCasamentoPreBoleto pTipoCasamentoPreBoleto)
        {
            BusinessEntity.RetornoCasamento retorno;
            ResourceAccess.PreBoleto preBoletoRA = new ResourceAccess.PreBoleto();
            preBoleto.Ordem.DataPregao = preBoleto.DataPregao;
            retorno = preBoletoRA.RealizarCasamento(preBoleto.Ordem, pTipoCasamentoPreBoleto);
            if (retorno == null) return null;

            RealizarAcoesPosCasamentoDescasamento(preBoleto, retorno, "Casamento de Pré-Boletos");

            return retorno;
        }

        /// <summary>
        /// Metodo responsavel por realizar o descasamento de pre-boletos
        /// Data: 14/12/2007
        /// Autor: Diogo Milanez
        /// Obs: Criacao do metodo
        /// </summary>
        /// <param name="preBoleto"></param>
        public BusinessEntity.RetornoCasamento RealizarDescasamento(BusinessEntity.PreBoleto preBoleto)
        {
            BusinessEntity.RetornoCasamento retorno;
            ResourceAccess.PreBoleto preBoletoRA = new ResourceAccess.PreBoleto();
            preBoletoRA.RealizarDescasamento(preBoleto);
            retorno = new BusinessEntity.RetornoCasamento();
            RealizarAcoesPosCasamentoDescasamento(preBoleto, retorno, "Descasamento de Pré-Boletos");
            return retorno;
        }

        /// <summary>
        /// Metodo responsavel por realizar acoes pos Casamento / Descasamento
        /// Acoesrealizadas:
        /// Verificacao Saldo Negociavel
        /// Verificacao Compliance
        /// Execucao Calculo Financeiro
        /// 
        /// </summary>
        /// <param name="preBoleto"></param>
        /// <param name="casar"></param>
        /// <param name="ordemBL"></param>
        /// <param name="ordemRA"></param>
        /// <param name="retorno"></param>
        private void RealizarAcoesPosCasamentoDescasamento(BusinessEntity.PreBoleto preBoleto, BusinessEntity.RetornoCasamento retorno, string origem)
        {
            BusinessLogic.Ordem ordemBL = new BusinessLogic.Ordem();
            ResourceAccess.Ordem ordemRA = new ResourceAccess.Ordem();

            Sinacor.Servico.Bovespa.Parametro.BusinessLogic.Parametro param = new Sinacor.Servico.Bovespa.Parametro.BusinessLogic.Parametro();

            ///se o parametro na torparm indicar que devera ser executa a verificacao do saldo
            string parmVerificaSaldo = param.RecuperarIndicadorVerificacaoSaldoNegociavel();
            if (parmVerificaSaldo == "S")
            {
                ///se a natureza de operacao for venda
                preBoleto.Ordem.NaturezaOperacao = ordemRA.ConsultarNaturezaOperacao(preBoleto.Ordem);
                if (preBoleto.Ordem.NaturezaOperacao == Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoNaturezaOperacao.Venda)
                {
                    ///recuperar informacoes de ordem necessarias para executar a verificacao de saldo
                    preBoleto.Ordem.CodigoCliente = ordemRA.ConsultarCodigoCliente(preBoleto.Ordem);
                    preBoleto.Ordem.Titulo = ordemRA.ConsultarCodigoNegociacao(preBoleto.Ordem);
                    preBoleto.Ordem.TipoMercado = StringToEnum(ordemRA.ConsultarMercado(preBoleto.Ordem));
                    preBoleto.Ordem.Quantidade = ordemRA.ConsultarQuantidade(preBoleto.Ordem);

                    ///executar a verificacao do saldo negociavel
                    string msgRetorno = ordemRA.VerficarSaldoNegociavel(preBoleto.Ordem);
                    retorno.MensagemVerificacaoSaldo.Descricao = msgRetorno;
                    retorno.MensagemVerificacaoSaldo.Codigo = 0;

                    ///executar o calculo financeiro
                    //20080424 16:42 - RValadao
                    //Passa a data do pregao do pre boleto para a ordem.
                    if (!preBoleto.Ordem.DataPregao.HasValue) preBoleto.Ordem.DataPregao = preBoleto.DataPregao;
                    ordemRA.RealizarCalculoFinanceiro(preBoleto.Ordem, origem);

                    ///se o casamento for total ou parcial
                    if (retorno.TipoRetornoCasamento == Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoRetornoCasamento.CasamentoTotal
                        || retorno.TipoRetornoCasamento == Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoRetornoCasamento.CasamentoParcial
                        )
                    {
                        /*
                         * Comentado por: rscatulin
                         * Em: 08 10 06 - 15:32
                         * Motivo: Nemir nos comunicou que existe um modulo separado para realizar
                         *  esta verificação, por esse motivo isto está desativado.
                        //se o parametro de execucao de verificacao de compliance for S
                        if (param.RecuperarIndicadorUtilizacaoCompliance() == "S")
                        {
                            ///executar a verificacao de compliance
                            msgRetorno = ordemBL.VerificarCompliance(preBoleto.Ordem);
                            retorno.MensagemVerificacaoCompliance.Codigo = 0;
                            retorno.MensagemVerificacaoCompliance.Descricao = msgRetorno;
                        }*/
                    }
                }
            }
        }

        /// <summary>
        /// Metodo responsavel por alterar determinado pré-boleto
        /// Data: 16/04/2008
        /// Autor: Ricardo Valadão Silva
        /// Obs: Como não existe método para alterar então é feito a exclusão e inclusão do pre boleto.
        /// </summary>
        /// <param name="request">colecao de pre-boletos para alteração</param>
        /// o casamento de pre-boletos apos a inclusao da colecao de pre-boletos informada</param>
        public BusinessEntity.RetornoCasamento AlterarPreBoleto(List<BusinessEntity.PreBoleto> request)
        {
            if (request == null || request.Count == 0)
                throw new BusinessException(ERRO_PREBOLETONAOINFORMADO);
            //Realiza a exclusão dos pré boletos
            EfetuarExclusaoPreBoleto(request, true);

            //Realiza a inclusão dos pré boletos com os valores atualizados
            //incluir pre-boletos
            EfetuarInclusaoPreBoleto(request, false);
            return RealizarCasamentoESP(request[0]);
        }

        #region Validacoes
        /// <summary>
        /// Metodo responsavel por validar os dados de inclusao de pre-boletos
        /// Data: 21/11/2007
        /// Autor: Diogo Milanez
        /// Obs: Criacao do metodo
        /// </summary>
        /// <param name="preBoletos"></param>
        private void ValidarDadosInclusao(List<BusinessEntity.PreBoleto> preBoletos)
        {
            ///validacoes de entrada de dados
            ValidationException ex = new ValidationException();
            int codErro;

            foreach (BusinessEntity.PreBoleto preBoleto in preBoletos)
            {
                codErro = ValidarContraParte(preBoleto);
                if (codErro > 0)
                    ex.AddError(codErro);

                codErro = ValidarCambio(preBoleto);
                if (codErro > 0)
                    ex.AddError(codErro);

                codErro = ValidarPreco(preBoleto);
                if (codErro > 0)
                    ex.AddError(codErro);

                if (ex.ValidationErrors != null && ex.ValidationErrors.Count > 0)
                {
                    throw ex;
                }

                ValidarEstrategia(preBoleto);
            }

            ValidarOrdem(preBoletos[0]);
            ValidarQuantidadeNegocio(preBoletos);
        }

        /// <summary>
        /// Metodo responsavel por validar os dados de pre-boleto antes da exclusao dos mesmos
        /// </summary>
        /// <param name="preBoleto"></param>
        private void ValidarDadosExclusao(BusinessEntity.PreBoleto preBoleto)
        {
            ValidarOrdem(preBoleto);
        }

        /// <summary>
        /// Metodo responsavel por verificar a exitencia da ordem passada como parametro
        /// </summary>
        /// <param name="preBoleto"></param>
        /// <returns></returns>
        private void ValidarOrdem(BusinessEntity.PreBoleto preBoleto)
        {
            ResourceAccess.Ordem ordemRA = new ResourceAccess.Ordem();
            if (!ordemRA.VerificarExistencia(preBoleto.Ordem))
                throw new BusinessException(ERRO_ORDEMINEXISTENTE);
        }

        private void ValidarQuantidadeNegocio(List<BusinessEntity.PreBoleto> request)
        {
            Sinacor.Servico.Bovespa.Parametro.BusinessLogic.Parametro param = new Sinacor.Servico.Bovespa.Parametro.BusinessLogic.Parametro();

            if (request == null || request.Count == 0)
                return;

            ///**VALIDACAO**
            /// A quantidade digitada na linha deve obedecer o lote mínimo de negociação 
            /// ( TBOTITLOT.NR_LOTNEG ) e ser múltiplo deste lote:
            decimal qtdeNegocio = 0;

            ///Recuperar a quantidade minima do lote de negociacao
            int? qtdeMinimaNegociacao;
            Titulo.BusinessEntity.Titulo titulo = new Titulo.BusinessEntity.Titulo();
            titulo.DataPregao = request[0].DataPregao;
            titulo.Codigo = (new ResourceAccess.Ordem()).ConsultarCodigoNegociacao(request[0].Ordem);

            if (string.IsNullOrEmpty(titulo.Codigo))
                throw new BusinessException(ERRO_TITULONAOENCONTRADO);

            qtdeMinimaNegociacao = (new Titulo.BusinessLogic.Titulo()).ConsultarQuantidadeMinimaLoteNegociacao(titulo);

            if (!qtdeMinimaNegociacao.HasValue)
            {
                throw new BusinessException(ERRO_TITULONAOENCONTRADO);
            }

            foreach (BusinessEntity.PreBoleto preBoleto in request)
            {
                if (preBoleto.QuantidadeNegocio <= 0 || preBoleto.QuantidadeNegocio < qtdeMinimaNegociacao
                    || (preBoleto.QuantidadeNegocio % qtdeMinimaNegociacao) != 0)
                {
                    throw new BusinessException(ERRO_QUANTIDADENEGOCIOINVALIDA);
                }

                ///calcular a quantidade de negocio total de todas as linhas do pre-boleto
                qtdeNegocio += preBoleto.QuantidadeNegocio;
            }            

            ///verificar parametro na torparm que indica se o saldo da ordem devera ser atualizado
            ///no caso da quantidade do pre-boleto ser superior ao saldo da ordem
            string inBoletoAtuOrdem = param.RecuperarIndicadorAtualizacaoQuantidadeOrdemPreBoleto();

            ///se o saldo n sera atualizado, entao devera validar a qntidade de negocio
            ///de acordo com o saldo
            BusinessLogic.Ordem ordemBL = new BusinessLogic.Ordem();
            ///recuperar saldo da ordem
            decimal saldo = ordemBL.RecuperarSaldo(request[0].Ordem);

            if (inBoletoAtuOrdem != "S")
            {
                if (qtdeNegocio > saldo)
                {
                    throw new BusinessException(ERRO_QUANTIDADENEGOCIOINVALIDA);
                }
            }
            else
            {
                ///se a quantidade do negocio foi maior do que o saldo
                ///atualizar a quantidade da ordem com a diferenca entre os valores
                if (qtdeNegocio > saldo)
                {
                    BusinessEntity.Ordem ordem = new BusinessEntity.Ordem();
                    ordem.DataOrdem = request[0].Ordem.DataOrdem;
                    ordem.NumeroOrdem = request[0].Ordem.NumeroOrdem;
                    ordem.NumeroOrdemSubSequencia = request[0].Ordem.NumeroOrdemSubSequencia;
                    ordem.Quantidade = qtdeNegocio - saldo;
                    ordemBL.IncrementarQuantidadeOrdem(ordem);
                }
            }
        }

        /// <summary>
        /// Validacao de Negocio relacionada ao preco
        /// Historico:
        /// Data: 28/11/2007
        /// Autor: Diogo Milanez
        /// Observacoes: retorno do metodo foi alterado para void
        /// 
        /// Regra:
        /// * preço deve ser maior do que zero;
        /// * para ordem limitada ou ordem on-stop se a natureza de operação for compra 
        /// o preço deve ser <= preço limite , se a natureza for venda o preço deve ser >= preço limite. 
        /// O preço limite deve ser recuperado em torpreco.vl_prepap e na não existencia de registros
        /// nessa tabela, é utilizado tormovd.vl_prepap. 
        /// </summary>
        /// <param name="preBoleto"></param>
        /// <returns></returns>
        private int ValidarPreco(BusinessEntity.PreBoleto preBoleto)
        {
            ///validacao de entrada de dados
            if (preBoleto.Preco < 0)
                return ERRO_PRECOINVALIDO;

            ///validacoes de negocio
            ///recuperar o tipo da ordem						
            BusinessLogic.Ordem ordemBL = new BusinessLogic.Ordem();
            Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoOrdem? tipoOrdem = ordemBL.ConsultarTipoOrdem(preBoleto.Ordem);

            ///se o tipo da ordem foi limitada ou onstop
            if (tipoOrdem == Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoOrdem.Limitada
                || tipoOrdem == Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoOrdem.OnStop)
            {
                ///consultar o preco limite da ordem
                decimal? precoLimite = ordemBL.ConsultarPrecoLimite(preBoleto.Ordem);
                ///consultar a natureza de operacao
                Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoNaturezaOperacao? tipoNatureza = ordemBL.ConsultarNaturezaOperacao(preBoleto.Ordem);

                ///se for uma compra
                if (tipoNatureza == Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoNaturezaOperacao.Compra)
                {
                    //se o preco foi superior ao precolimite
                    if (preBoleto.Preco > precoLimite)
                        throw new BusinessException(ERRO_PRECOINVALIDO);
                }
                //se for uma venda
                else if (tipoNatureza == Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoNaturezaOperacao.Venda)
                {
                    //se o preco for inferior ao preco limite
                    if (preBoleto.Preco < precoLimite)
                        throw new BusinessException(ERRO_PRECOINVALIDO);
                }
            }

            return 0;
        }
        private int ValidarContraParte(BusinessEntity.PreBoleto preBoleto)
        {
            if (preBoleto.ContraParte < 0)
                return ERRO_CONTRAPARTEINVALIDA;
            else
                return 0;
        }

        ///Diogo Milanez - 21/11/2007
        ///Metodo Removido
        //private int ValidarTipoCasamento(BusinessEntity.PreBoleto preBoleto)
        //{
        //    return 0;
        //}

        /// <summary>
        /// Metodo responsavel por validar a estrategia do preboleto de acordo
        /// com o mercado da ordem.
        /// Regra:
        /// Se mercado = OPC ou mercado = OPV:
        /// Estrategia pode ser N,B,D,P
        /// Se mercado = EOC ou mercado = EOV:
        /// Estratégia pode ser N,D
        /// Se mercado = VIS:
        /// Estratégia pode ser N,P
        /// Se a estratégia não for informada (NULL) será assumido o valor N"
        /// </summary>
        /// <param name="preBoleto"></param>
        private void ValidarEstrategia(BusinessEntity.PreBoleto preBoleto)
        {
            ///se nao for informado o tipo de estrategia,
            ///sera assumida a estrategia "Nenhum" (N)
            if (!preBoleto.TipoEstrategia.HasValue)
                preBoleto.TipoEstrategia = Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoEstrategia.Nenhuma;

            ///se o tipo de estrategia for nenhum
            ///nao precisa realiza as validacoes pois todos os mercados aceitam 
            ///o tipo de estrategina "Nenhum" (N)
            if (preBoleto.TipoEstrategia == Sinacor.Servico.Bovespa.Ordens.BusinessEntity.Enum.TipoEstrategia.Nenhuma)
                return;

            BusinessLogic.Ordem ordem = new BusinessLogic.Ordem();
            string mercado = ordem.RecuperarMercado(preBoleto.Ordem);

            if (mercado == "OPC" || mercado == "OPV")
            {
                if (preBoleto.TipoEstrategia != TipoEstrategia.POP
                    && preBoleto.TipoEstrategia != TipoEstrategia.BOX
                    && preBoleto.TipoEstrategia != TipoEstrategia.DBX
                    )
                    throw new BusinessException(ERRO_ESTRATEGIAINVALIDA);
            }
            else if (mercado == "EOC" || mercado == "EOV")
            {
                if (preBoleto.TipoEstrategia != TipoEstrategia.Nenhuma
                    && preBoleto.TipoEstrategia != TipoEstrategia.DBX)
                    throw new BusinessException(ERRO_ESTRATEGIAINVALIDA);
            }
            else if (mercado == "VIS")
            {
                if (preBoleto.TipoEstrategia != TipoEstrategia.Nenhuma
                    && preBoleto.TipoEstrategia != TipoEstrategia.POP)
                    throw new BusinessException(ERRO_ESTRATEGIAINVALIDA);
            }

            return;
        }

        private int ValidarCambio(BusinessEntity.PreBoleto preBoleto)
        {
            if (preBoleto.Cambio.HasValue && preBoleto.Cambio < 0)
                return ERRO_CAMBIOINVALIDO;
            else
                return 0;
        }


        #endregion

        ///<sumary>
        /// Converte Tipo de Mercado de String para Enum
        /// Data: 11/12/2007
        /// Autor: Eduarddo Sertorio
        /// Observacoes: Criacao do enum
        /// 
        /// Data:28/01/2008 16:50
        /// Autor:Dmilanez.7comm
        /// Obs:
        /// Alterado de forma a conter o mercado BOX
        ///<sumary>
        public static BusinessEntity.Enum.TipoMercado? StringToEnum(string value)
        {
            BusinessEntity.Enum.TipoMercado? retorno;
            switch (value)
            {
                case "VIS":
                    retorno = BusinessEntity.Enum.TipoMercado.Vista;
                    break;
                case "OPC":
                    retorno = BusinessEntity.Enum.TipoMercado.OpcaoCompra;
                    break;
                case "OPV":
                    retorno = BusinessEntity.Enum.TipoMercado.OpcaoVenda;
                    break;
                case "EOC":
                    retorno = BusinessEntity.Enum.TipoMercado.ExercicioOpcaoCompra;
                    break;
                case "EOV":
                    retorno = BusinessEntity.Enum.TipoMercado.ExercicioOpcaoVenda;
                    break;
                case "FRA":
                    retorno = BusinessEntity.Enum.TipoMercado.Fracionario;
                    break;
                case "EST":
                    retorno = BusinessEntity.Enum.TipoMercado.Estruturado;
                    break;
                case "LEI":
                    retorno = BusinessEntity.Enum.TipoMercado.Leilao;
                    break;
                case "TER":
                    retorno = BusinessEntity.Enum.TipoMercado.Termo;
                    break;
                case "LNC":
                    retorno = BusinessEntity.Enum.TipoMercado.LeilaoNaoCotados;
                    break;
                case "FUT":
                    retorno = BusinessEntity.Enum.TipoMercado.Futuro;
                    break;
                case "VFU":
                    retorno = BusinessEntity.Enum.TipoMercado.VencimentoFuturo;
                    break;
                case "BOX":
                    retorno = BusinessEntity.Enum.TipoMercado.BOX;
                    break;
                case "IER":
                    retorno = BusinessEntity.Enum.TipoMercado.IntegralizacaoResgateCotas;
                    break;
                case "CET":
                    retorno = BusinessEntity.Enum.TipoMercado.CotasETF;
                    break;
                default:
                    retorno = null;
                    break;
            }
            return retorno;
        }

        ///<sumary>
        /// Converte Tipo de Mercado de Enum para String
        /// Data: 11/12/2007
        /// Autor: Eduarddo Sertorio
        /// Observacoes: Criacao do enum
        /// 
        /// Data:28/01/2008 16:50
        /// Autor:Dmilanez.7comm
        /// Obs:
        /// Alterado de forma a conter o mercado BOX
        ///<sumary>
        public static string EnumToString(BusinessEntity.Enum.TipoMercado value)
        {
            string retorno;
            switch (value)
            {
                case BusinessEntity.Enum.TipoMercado.Vista:
                    retorno = "VIS";
                    break;
                case BusinessEntity.Enum.TipoMercado.OpcaoCompra:
                    retorno = "OPC";
                    break;
                case BusinessEntity.Enum.TipoMercado.OpcaoVenda:
                    retorno = "OPV";
                    break;
                case BusinessEntity.Enum.TipoMercado.ExercicioOpcaoCompra:
                    retorno = "EOC";
                    break;
                case BusinessEntity.Enum.TipoMercado.ExercicioOpcaoVenda:
                    retorno = "EOV";
                    break;
                case BusinessEntity.Enum.TipoMercado.Fracionario:
                    retorno = "FRA";
                    break;
                case BusinessEntity.Enum.TipoMercado.Estruturado:
                    retorno = "EST";
                    break;
                case BusinessEntity.Enum.TipoMercado.Leilao:
                    retorno = "LEI";
                    break;
                case BusinessEntity.Enum.TipoMercado.Termo:
                    retorno = "TER";
                    break;
                case BusinessEntity.Enum.TipoMercado.LeilaoNaoCotados:
                    retorno = "LNC";
                    break;
                case BusinessEntity.Enum.TipoMercado.Futuro:
                    retorno = "FUT";
                    break;
                case BusinessEntity.Enum.TipoMercado.VencimentoFuturo:
                    retorno = "VFU";
                    break;
                case BusinessEntity.Enum.TipoMercado.BOX:
                    retorno = "BOX";
                    break;
                case BusinessEntity.Enum.TipoMercado.IntegralizacaoResgateCotas:
                    retorno = "IER";
                    break;
                case BusinessEntity.Enum.TipoMercado.CotasETF:
                    retorno = "CET";
                    break;
                default: //BusinessEntity.Enum.TipoMercado.Indefinido
                    retorno = "";
                    break;
            }
            return retorno;
        }

        public static string EnumToString(BusinessEntity.Enum.TipoMercado? value)
        {
            if (value.HasValue)
                return EnumToString(value.Value);
            else
                return null;
        }
    }
}
